package webServer;

import HTTP.*;

import java.net.*;
import java.util.*;
import java.io.*;

import org.w3c.dom.*;

import com.herohead.Misc;
import com.herohead.PushCo;

/**
 * Handles requests for files.  This can't dynamicly generate content.
 * A short configuration file is in data\fileHandlerConfig.xml.
 */
public class FileHTTPRequestHandler implements HTTPRequestHandler
{
	private static final File CONFIG_FILE = new File("data\\fileHandlerConfig.xml");
	private static String targetDirectory = loadConfigurationAndGetTargetDirectory();

	private static String loadConfigurationAndGetTargetDirectory()
	{
		String result = "public_html";
		try
		{
			Document doc = XMLParser.getDocumentFor(CONFIG_FILE);
			NodeList nl = doc.getElementsByTagName("targetDirectory");
			if (nl.getLength() > 0)
			{
				Element e = (Element)nl.item(0);
				String dir = e.getAttribute("value");
				if (dir != null)
				{
					result = dir;

					// Be flexible if the user thought he should include a trailing slash.
					if (result.endsWith("\\") || result.endsWith("/"))
						result = result.substring(0, result.length() - 1);
				}
			}
		}
		catch (Throwable t)
		{
			t.printStackTrace();
			System.err.println("Unable to load configuration from "+CONFIG_FILE);
		}
		return result;
	}

	public boolean canHandle(HTTPRequest request)
	{
		return true;
	}

	/**
	 * Gets HTML formatted info for the specified file
	 */
	private String getFileInfoContentFor(File parent,File f,boolean needsDirectoryNameInRelativeAddresses)
	{
		String hrefPath = f.getName();

		if (needsDirectoryNameInRelativeAddresses)
		{
			hrefPath = parent.getName() + "/" + hrefPath;
		}
		String result = "<a href=\"" + hrefPath + "\">" + f.getName() + "</a>";


		return result;
	}

	/**
	 * Tries to get contents from an index page within the specified directory.
	 * @return null if no index page is found.
	 */
	private byte[] getIndexPageContentsForDirectory(File dir)
	{ 
		String []indexPageNames = new String[]
				{"index.html","index.htm","default.html","default.htm"}; 

		byte[] result = null;
		for (String pageName: indexPageNames)
		{
			result = getFileContents(dir, pageName);
			if (result!=null)
				return result;
		}

		return null;
	}

	/**
	 * Automatically generates indexing content for a directory.
	 * @param requestPath may seem redundant but it is needed to 
	 * determine if the browser needs the directory name in relative addresses.  
	 * The directory name is needed in relative addresses if and only if '/' is not 
	 * at the end of the request path. 
	 */
	private byte[] getContentForDirectory(File dir,boolean needsDirectoryNameInRelativeAddresses)
	{
		if (!dir.isDirectory())
		{
			System.err.println("FileHTTPRequestHandler getContentForDirectory expected a directory instead of ");
		}
		byte[] indexPageContents = getIndexPageContentsForDirectory(dir);
		if (indexPageContents != null)
			return indexPageContents;
		try
		{
			ByteArrayOutputStream bout = new ByteArrayOutputStream();
			PrintStream out = new PrintStream(bout);
			File[] files = dir.listFiles();
			out.println("<html>");
			out.println(" <head>");
			out.println("  <title>Directory '"+dir.getName()+"'</title>");
			out.println(" </head>");
			out.println("<body>");
			out.println("  <h1>Directory '" + dir.getName() + "'</h1><hr />");
			out.println("<ul>");
			out.println("<li>");
			// loop through these files
			for (int i = 0; i < files.length; i++)
			{
				File f = files[i];
				out.println("  <li>"+getFileInfoContentFor(dir,f,needsDirectoryNameInRelativeAddresses)+"</li>");
			}
			out.println("</ul><hr />");

			out.println("Generated by Simple Web Server");
			out.println("</body></html>");
			return bout.toByteArray();
		}
		catch (Throwable t)
		{
			t.printStackTrace();
			System.err.println("Unable to create directory content");
		}
		return (""+dir.getName()).getBytes();
	}

	/**
	 * @param filePath is the path sent from the HTTP request.  
	 * The specified file would be within the targetDirectory.
	 * @return null if the file doesn't exist.
	 */
	private byte[] getFileContents(String filePath)
	{
		return getFileContents(getFileFrom(filePath));
	}

	private File getFileFrom(String filePath)
	{
		return getFileFrom(new File(targetDirectory),filePath);
	}

	private File getFileFrom(File parentDirectory, String filePath)
	{ 
		final String separator = System.getProperty("file.separator");
		if (filePath.startsWith(separator))
		{
			filePath = filePath.substring(separator.length());
		}
		File f = new File(parentDirectory + separator + filePath);
		return f;
	}

	private byte[] getFileContents(File parentDirectory, String filePath)
	{
		return getFileContents(getFileFrom(parentDirectory, filePath));
	}

	/**
	 * Gets the contents of the specified file.
	 * @return null if there is a problem.
	 */
	private byte[] getFileContents(File f)
	{
		if (!f.exists())
			return null;
		try
		{
			InputStream in = new FileInputStream(f);
			byte[] data = new byte[(int)f.length()];
			int position = 0;
			while (position < data.length)
			{
				int numBytesRead = in.read(data,position,data.length-position);
				if (numBytesRead < 0)
				{
					throw new EOFException("Unexpected end of file in '"+f.getAbsolutePath()+"' "
							+position+" bytes were read in until the end.  "
							+data.length+" was the expected length.");
				}
				position += numBytesRead;
			}
			return data;
		}
		catch (Throwable t)
		{
			t.printStackTrace();
			System.err.println("Unable to read from requested file: "+f);
		}
		return null;
	}

	private byte[] get404ResponseContents()
	{
		byte[] result = getFileContents("404.html");
		if (result == null)
			return "<html>404 - File not found</html>".getBytes();
		else
			return result;
	}

	/**
	 * Gets an appropriate response to a request for the specified file.
	 * If the file doesn't exist or can't be read 404 is returned.
	 * If the file is a directory, an index page is searched for.  
	 * If an index page isn't found, one is automatically generated.
	 */
	private HTTPResponse getResponseForFile(String filePath,String param,boolean needsDirectoryNameInRelativeAddresses)
	{
		HTTPResponse response = new HTTPResponse();

		// new code below.

		System.out.println(filePath);



		PushCo pc = new PushCo();
		Misc m = new Misc();

		String req = null;
		String message = null;
		//String param = null;

		// cde = craig david execute :-)

		if (filePath.contains("\\nw\\cde.")) {
			if (filePath.contains("?")) {
				req = filePath.substring(filePath.indexOf("\\nw\\cde.")+ 4, filePath.indexOf("?"));
				param = filePath.substring(filePath.indexOf("?"), filePath.length());
			} else {
				req = filePath.substring(filePath.indexOf("\\nw\\cde.")+ 4, filePath.length());
			}
			if (req.equals("cde.AvamarMonthly")) {
				String sDate = null;
				String eDate= null;
				
				sDate = param.substring(param.indexOf("=") +1 , param.indexOf("&"));
				eDate = param.substring(param.indexOf("endDate="), param.length());
				eDate = eDate.split("=")[1];
				System.out.println(sDate);
				System.out.println(eDate);
				
				try {
					String s = Misc.callex("L:\\My Documents\\2014\\av_monthlyReports\\av_run.cmd " + sDate + " " + eDate);
					String ss[] = s.split("\n");
						s = "";
						  for (int i=0; i<ss.length; i++) {
						    s = s + ss[i] + "<br>";
						  }
						
					
					
					response.setContent(s);
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				
				//response.setContent("AvamarMonthly");
				
				
				
				
			} else if (req.equals("cde.push.co")) {
				pc.setKey("0029c8745fcc0078ed43f17f4562a9165eb46de90607fbfd5b885ff22714");
				pc.setSecret("7e5cdd71088a7766084d48f19b9088f4253920702eb378b04a54196d16c25d85");		
				System.out.println(param);
				try {
					message = param.split("=")[1].replace("_", " ");
					message = message.replace("+", " ");
					pc.sendMessage(message);
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				response.setContent("Message pushed - " + message);
			} 






			//response.setContent(req + param);
			//return response;
		} else {

			//********* new code above

			File f = getFileFrom(filePath);
			byte[] contents = null;
			if (f.isDirectory())
			{
				contents = getContentForDirectory(f, needsDirectoryNameInRelativeAddresses);
			}
			else
				contents = getFileContents(f);

			try
			{
				if (contents == null)
				{ // file not found or problem reading from file 
					response.setReponseCodeNumber(404);
					contents = get404ResponseContents();
					response.setContent(contents);
					response.setContentType("text/html");
				}
				else
				{
					if (!f.isDirectory())
						response.setContentType(ContentTypes.guessContentTypeFromPath(filePath));

					response.setContent(contents);
				}
			}
			catch (Throwable t)
			{
				t.printStackTrace();
				System.err.println("Problem generating response to client request for '"+filePath+"'.");
			}
		}
		return response;
	}

	public void handleRequest(HTTPRequest request)
	{ 
		/* try to handle the specified request by sending 
		 * a response to its socket's output stream
		 */



		String filePath = request.getFilePath();

		String param1 = request.getRequestPath();
		//System.out.println(param1);
		String param = param1.substring(param1.indexOf("?")+1,param1.length());

		//System.out.println(param);

		HTTPResponse response = getResponseForFile(filePath,param,!request.isForDirectory());

		try
		{
			/**
			 * Write the response to the client.
			 */

			//response.setContent("Cool");


			response.writeTo(request.getSocket().getOutputStream());
		}
		catch (Throwable t)
		{
			t.printStackTrace();
			System.err.println("Unable to properly respond to the client.");
		}
	}

}